from enum import Enum
from typing import List, Generic, TypeVar, Optional, Set
from fastapi import HTTPException
from pydantic import BaseModel, Field, field_validator, model_validator

from app.schemas.response import APIException


class OrderType(str, Enum):
    """排序类型"""

    ASC = "ASC"
    DESC = "DESC"


class OrderField(BaseModel):
    """排序字段"""

    field: str
    order: OrderType = OrderType.ASC


class OrderSchema(BaseModel):
    """排序Schema"""

    order_by: str = Field(
        default="", description="排序字段，多个字段用逗号分隔，字段名前加-表示降序，如：-created_at,id"
    )
    allowed_fields: Set[str] = Field(default_factory=set, exclude=True)

    @model_validator(mode="after")
    def validate_allowed_fields(self) -> "OrderSchema":
        """验证排序字段是否在允许的范围内"""
        if not self.allowed_fields:
            return self

        for field in self.get_orders():
            if field.field not in self.allowed_fields:
                raise APIException(message=f"字段 {field.field} 不允许排序")
        return self

    @field_validator("order_by")
    def validate_order_by(cls, v: str) -> str:
        """验证排序字段"""
        if not v:
            return v

        # 验证每个排序字段
        for field in v.split(","):
            if not field:
                continue
            if field.startswith("-"):
                field = field[1:]
            if not field:
                raise ValueError("排序字段不能为空")
        return v

    def get_orders(self) -> List[OrderField]:
        """解析排序字段"""
        if not self.order_by:
            return []

        orders = []
        for field in self.order_by.split(","):
            if not field:
                continue
            if field.startswith("-"):
                orders.append(OrderField(field=field[1:], order=OrderType.DESC))
            else:
                orders.append(OrderField(field=field, order=OrderType.ASC))
        return orders

    def get_tortoise_orders(self) -> List[str]:
        """获取Tortoise ORM格式的排序字段列表"""
        return [f"{'-' if order.order == OrderType.DESC else ''}{order.field}" for order in self.get_orders()]

    @classmethod
    def with_allowed_fields(cls, allowed_fields: Set[str], order_by: str = "") -> "OrderSchema":
        """创建一个带有允许排序字段的实例"""
        return cls(allowed_fields=allowed_fields, order_by=order_by)


T = TypeVar("T")


class PaginationParams(BaseModel):
    """分页参数"""

    page: int = Field(default=1, ge=1, description="页码")
    page_size: int = Field(default=20, ge=1, le=100, description="每页数量")

    def get_skip(self) -> int:
        """获取跳过的记录数"""
        return (self.page - 1) * self.page_size


class PaginationResult(BaseModel, Generic[T]):
    """分页结果"""

    total: int
    items: List[T]
